﻿// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.TypeSpec.Generator.Customizations;

namespace Azure.AI.DocumentIntelligence
{
    // CUSTOM CODE NOTE: the generator started including AnalyzeDocumentOptions, ClassifierDocumentTypeDetails,
    // and ClassifyDocumentOptions in the factory after we hid their parameterless constructors. This is unnecessary
    // given that they are input-only models that can be directly instantiated by users. For this reason we're
    // suppressing their generation here.

    [CodeGenType("AIDocumentIntelligenceModelFactory")]
    [CodeGenSuppress("AnalyzeDocumentOptions", typeof(Uri), typeof(BinaryData))]
    [CodeGenSuppress("ClassifierDocumentTypeDetails", typeof(ContentSourceKind?), typeof(BlobContentSource), typeof(BlobFileListContentSource))]
    [CodeGenSuppress("ClassifyDocumentOptions", typeof(Uri), typeof(BinaryData))]
    public partial class DocumentIntelligenceModelFactory
    {
        // CUSTOM CODE NOTE: the AnalyzeResult method must be added manually to the factory.
        // It stopped being autogenerated after we hid its 'StringIndexType' property.

        private const string DefaultStringIndexType = "utf16CodeUnit";

        /// <summary> Initializes a new instance of <see cref="DocumentIntelligence.AnalyzeResult"/>. </summary>
        /// <param name="apiVersion"> API version used to produce this result. </param>
        /// <param name="modelId"> Document model ID used to produce this result. </param>
        /// <param name="contentFormat"> Format of the analyze result top-level content. </param>
        /// <param name="content">
        /// Concatenate string representation of all textual and visual elements in reading
        /// order.
        /// </param>
        /// <param name="pages"> Analyzed pages. </param>
        /// <param name="paragraphs"> Extracted paragraphs. </param>
        /// <param name="tables"> Extracted tables. </param>
        /// <param name="figures"> Extracted figures. </param>
        /// <param name="sections"> Extracted sections. </param>
        /// <param name="keyValuePairs"> Extracted key-value pairs. </param>
        /// <param name="styles"> Extracted font styles. </param>
        /// <param name="languages"> Detected languages. </param>
        /// <param name="documents"> Extracted documents. </param>
        /// <param name="warnings"> List of warnings encountered. </param>
        /// <returns> A new <see cref="DocumentIntelligence.AnalyzeResult"/> instance for mocking. </returns>
        public static AnalyzeResult AnalyzeResult(string apiVersion = null, string modelId = null, DocumentContentFormat? contentFormat = null, string content = null, IEnumerable<DocumentPage> pages = null, IEnumerable<DocumentParagraph> paragraphs = null, IEnumerable<DocumentTable> tables = null, IEnumerable<DocumentFigure> figures = null, IEnumerable<DocumentSection> sections = null, IEnumerable<DocumentKeyValuePair> keyValuePairs = null, IEnumerable<DocumentStyle> styles = null, IEnumerable<DocumentLanguage> languages = null, IEnumerable<AnalyzedDocument> documents = null, IEnumerable<DocumentIntelligenceWarning> warnings = null)
        {
            pages ??= new List<DocumentPage>();
            paragraphs ??= new List<DocumentParagraph>();
            tables ??= new List<DocumentTable>();
            figures ??= new List<DocumentFigure>();
            sections ??= new List<DocumentSection>();
            keyValuePairs ??= new List<DocumentKeyValuePair>();
            styles ??= new List<DocumentStyle>();
            languages ??= new List<DocumentLanguage>();
            documents ??= new List<AnalyzedDocument>();
            warnings ??= new List<DocumentIntelligenceWarning>();

            return new AnalyzeResult(
                apiVersion,
                modelId,
                DefaultStringIndexType,
                contentFormat,
                content,
                pages?.ToList(),
                paragraphs?.ToList(),
                tables?.ToList(),
                figures?.ToList(),
                sections?.ToList(),
                keyValuePairs?.ToList(),
                styles?.ToList(),
                languages?.ToList(),
                documents?.ToList(),
                warnings?.ToList(),
                additionalBinaryDataProperties: null);
        }

        // CUSTOM CODE NOTE: the AnalyzedDocument and DocumentField methods must be added manually to
        // the factory. It stopped being autogenerated after we replaced their
        // IReadOnlyDictionary<string, DocumentField> with our custom DocumentFieldDictionary type.

        /// <summary> Initializes a new instance of <see cref="DocumentIntelligence.AnalyzedDocument"/>. </summary>
        /// <param name="documentType"> Document type. </param>
        /// <param name="boundingRegions"> Bounding regions covering the document. </param>
        /// <param name="spans"> Location of the document in the reading order concatenated content. </param>
        /// <param name="fields"> Dictionary of named field values. </param>
        /// <param name="confidence"> Confidence of correctly extracting the document. </param>
        /// <returns> A new <see cref="DocumentIntelligence.AnalyzedDocument"/> instance for mocking. </returns>
        public static AnalyzedDocument AnalyzedDocument(string documentType = null, IEnumerable<BoundingRegion> boundingRegions = null, IEnumerable<DocumentSpan> spans = null, DocumentFieldDictionary fields = null, float confidence = default)
        {
            boundingRegions ??= new List<BoundingRegion>();
            spans ??= new List<DocumentSpan>();
            fields ??= new DocumentFieldDictionary();

            return new AnalyzedDocument(
                documentType,
                boundingRegions?.ToList(),
                spans?.ToList(),
                fields,
                confidence,
                additionalBinaryDataProperties: null);
        }

        /// <summary> Initializes a new instance of <see cref="DocumentIntelligence.DocumentField"/>. </summary>
        /// <param name="fieldType"> Data type of the field value. </param>
        /// <param name="valueString"> String value. </param>
        /// <param name="valueDate"> Date value in YYYY-MM-DD format (ISO 8601). </param>
        /// <param name="valueTime"> Time value in hh:mm:ss format (ISO 8601). </param>
        /// <param name="valuePhoneNumber"> Phone number value in E.164 format (ex. +19876543210). </param>
        /// <param name="valueDouble"> Floating point value. </param>
        /// <param name="valueInt64"> Integer value. </param>
        /// <param name="valueSelectionMark"> Selection mark value. </param>
        /// <param name="valueSignature"> Presence of signature. </param>
        /// <param name="valueCountryRegion"> 3-letter country code value (ISO 3166-1 alpha-3). </param>
        /// <param name="valueList"> Array of field values. </param>
        /// <param name="valueDictionary"> Dictionary of named field values. </param>
        /// <param name="valueCurrency"> Currency value. </param>
        /// <param name="valueAddress"> Address value. </param>
        /// <param name="valueBoolean"> Boolean value. </param>
        /// <param name="valueSelectionGroup"> Selection group value. </param>
        /// <param name="content"> Field content. </param>
        /// <param name="boundingRegions"> Bounding regions covering the field. </param>
        /// <param name="spans"> Location of the field in the reading order concatenated content. </param>
        /// <param name="confidence"> Confidence of correctly extracting the field. </param>
        /// <returns> A new <see cref="DocumentIntelligence.DocumentField"/> instance for mocking. </returns>
        public static DocumentField DocumentField(DocumentFieldType fieldType = default, string valueString = null, DateTimeOffset? valueDate = null, TimeSpan? valueTime = null, string valuePhoneNumber = null, double? valueDouble = null, long? valueInt64 = null, DocumentSelectionMarkState? valueSelectionMark = null, DocumentSignatureType? valueSignature = null, string valueCountryRegion = null, IEnumerable<DocumentField> valueList = null, DocumentFieldDictionary valueDictionary = null, CurrencyValue valueCurrency = null, AddressValue valueAddress = null, bool? valueBoolean = null, IEnumerable<string> valueSelectionGroup = null, string content = null, IEnumerable<BoundingRegion> boundingRegions = null, IEnumerable<DocumentSpan> spans = null, float? confidence = null)
        {
            valueList ??= new List<DocumentField>();
            valueDictionary ??= new DocumentFieldDictionary();
            valueSelectionGroup ??= new List<string>();
            boundingRegions ??= new List<BoundingRegion>();
            spans ??= new List<DocumentSpan>();

            return new DocumentField(
                fieldType,
                valueString,
                valueDate,
                valueTime,
                valuePhoneNumber,
                valueDouble,
                valueInt64,
                valueSelectionMark,
                valueSignature,
                valueCountryRegion,
                valueList?.ToList(),
                valueDictionary,
                valueCurrency,
                valueAddress,
                valueBoolean,
                valueSelectionGroup?.ToList(),
                content,
                boundingRegions?.ToList(),
                spans?.ToList(),
                confidence,
                additionalBinaryDataProperties: null);
        }

        /// <summary> Initializes a new instance of <see cref="DocumentIntelligence.DocumentFieldDictionary"/>. </summary>
        /// <param name="items"> The items of the dictionary. </param>
        /// <returns> A new <see cref="DocumentIntelligence.DocumentFieldDictionary"/> instance for mocking. </returns>
        public static DocumentFieldDictionary DocumentFieldDictionary(IReadOnlyDictionary<string, DocumentField> items)
        {
            items ??= new Dictionary<string, DocumentField>();

            return new DocumentFieldDictionary(items);
        }
    }
}
